package org.zjvis.datascience.common.sql;

import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.util.TablesNamesFinder;
import org.apache.commons.collections.CollectionUtils;
import org.zjvis.datascience.common.model.DimensionConfig;

import java.sql.Types;
import java.util.List;
import java.util.Map;

/**
 * @description : SQL语法拼装帮助类
 * @date 2021-11-01
 */
public class SqlSyntaxHelper {

    private Map<String, Integer> columnTypes;

    public Map<String, Integer> getColumnTypes() {
        return columnTypes;
    }

    public void setColumnTypes(Map<String, Integer> columnTypes) {
        this.columnTypes = columnTypes;
    }

    public boolean isTimestamp(DimensionConfig config) {
        int type = columnTypes.get(config.getFieldName().toUpperCase());
        return Types.TIMESTAMP == type || Types.TIMESTAMP_WITH_TIMEZONE == type;
    }

    public boolean isNumber(DimensionConfig config) {
        int type = columnTypes.get(config.getFieldName().toUpperCase());
        return isNumber(type);
    }

    public static boolean isNumber(Integer type) {
        return Types.BIGINT == type || Types.INTEGER == type || Types.DECIMAL == type || Types.FLOAT == type ||
                Types.SMALLINT == type || Types.NUMERIC == type || Types.DOUBLE == type || Types.REAL == type;
    }

    public boolean isDate(DimensionConfig config) {
        int type = columnTypes.get(config.getFieldName().toUpperCase());
        return Types.DATE == type;
    }

    public static boolean isDate(Integer type) {
        return Types.TIMESTAMP == type || Types.TIMESTAMP_WITH_TIMEZONE == type || Types.DATE == type;
    }

    public boolean isLongVarchar(DimensionConfig config) {
        int type = columnTypes.get(config.getFieldName().toUpperCase());
        return Types.LONGVARCHAR == type;
    }

    public String getFieldStr(DimensionConfig config, int index) {
        switch (columnTypes.get(config.getFieldName().toUpperCase())) {
            case Types.VARCHAR:
            case Types.CHAR:
            case Types.NVARCHAR:
            case Types.NCHAR:
            case Types.CLOB:
            case Types.NCLOB:
            case Types.LONGVARCHAR:
            case Types.LONGNVARCHAR:
            case Types.DATE:
            case Types.TIMESTAMP:
            case Types.TIMESTAMP_WITH_TIMEZONE:
                return "'" + config.getValues().get(index).replaceAll("'", "''") + "'";
            default:
                return config.getValues().get(index);
        }
    }

    public static List<String> getTablesBySql(String sql) throws JSQLParserException {
        Statement statement = CCJSqlParserUtil.parse(sql);
        if (!(statement instanceof Select)) {
            throw new JSQLParserException("Must be Select Statement!");
        }
        Select selectStatement = (Select) statement;
        TablesNamesFinder tablesNamesFinder = new TablesNamesFinder();
        List<String> tableList = tablesNamesFinder.getTableList(selectStatement);
        if (CollectionUtils.isEmpty(tableList)) {
            throw new JSQLParserException("Illegal Sql, no table is defined!");
        }
        return tableList;
    }

    /**
     * @param key
     * @return
     */
    public Integer getColumnType(String key) {
        return columnTypes.get(key.toLowerCase()) == null ? columnTypes.get(key.toUpperCase())
                : columnTypes.get(key.toLowerCase());
    }
}
